package at.ac.tuwien.lsds.gui;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.log4j.BasicConfigurator;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import at.ac.tuwien.lsds.exception.SchedulerException;
import at.ac.tuwien.lsds.model.ScenarioEnum;
import at.ac.tuwien.lsds.model.ScheduleStrategyEnum;
import at.ac.tuwien.lsds.schedule.Scheduler;
import at.ac.tuwien.lsds.schedule.SchedulerImpl;
import at.ac.tuwien.lsds.testDataGenerator.InputDataGenerator;
import at.ac.tuwien.lsds.util.SchedulerOutputFile;
import at.ac.tuwien.lsds.util.Settings;

// einfach e(fx)clipse vom Marketplace installieren und JavaFX SDK als Library adden
public class GUI extends Application {
    
	private Text tx_generator = new Text("Generator");
	
	Label lbl_numberOfApps = new Label("Number of Apps");
	TextField txf_numberOfApps = this.getNewNumTextField(Settings.getGeneratorNumberOfApps().toString());
	
	Label lbl_genOutputPath = new Label("Generator Output Path (creates 3 Files)");
	Button btn_genOutputPath = new Button("select");
	final Text tx_genOutputPath = new Text(Settings.getGeneratorDirectory());
	
	Button btn_generator = new Button("GENERATE");
	
	
	
	private Text tx_settings = new Text("Settings");
	
	Label lbl_inputFileApps = new Label("Input File (Apps)");
	Button btn_inputFileApps = new Button("select");
	final Text tx_inputFileApps = new Text(Settings.getInputFilePath());
	
	Label lbl_csvSeparator = new Label("CSV Separator");
	final ComboBox<String> cbx_csvSeparator = new ComboBox<String>();
	
	Label lbl_PMs = new Label("Physical Machines");
	TextField txf_PMs = this.getNewNumTextField(Settings.getPmCount().toString());
	
	Label lbl_cloudPartner = new Label("Cloud partner");
	TextField txf_cloudPartner = this.getNewNumTextField(Settings.getCloudPartnerCount().toString());
	
	Label lbl_scenario = new Label("Scenario");
	final ComboBox<ScenarioEnum> cbx_scenario = new ComboBox<ScenarioEnum>();
	
	Label lbl_scheduler = new Label("Scheduler");
	final ComboBox<ScheduleStrategyEnum> cbx_scheduler = new ComboBox<ScheduleStrategyEnum>();
	
	Label lbl_outputPath = new Label("Output Path");
	Button btn_outputPath = new Button("select");
	final Text tx_outputPath = new Text(Settings.getSchedulerOutputDirectory());
	
	Button btn_reset = new Button("reset");
	Button btn_start = new Button("START");
	
	public static void main(String[] args) {
		BasicConfigurator.configure();
    	Settings.resetToDefault();
        launch(args);
    }
    
    @Override
    public void start(final Stage primaryStage) {
        primaryStage.setTitle("LSDS Assignment (SS13, Group 7)");
        
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(5);
        grid.setVgap(5);
        grid.setPadding(new Insets(25, 25, 25, 25));

        ColumnConstraints col1 = new ColumnConstraints();
        col1.setMinWidth(200);
        ColumnConstraints col2 = new ColumnConstraints();
        col2.setMinWidth(200);
        grid.getColumnConstraints().addAll(col1,col2);
        
        int row = 0;
        
        /** +++++++++++++ GENERATOR Title (0) ++++++++++++++ **/
        tx_generator.setId("tx_generator");
        grid.add(tx_generator, 0, row++, 2, 1);
        
        // ---------------- SEPARATOR ---------------- //
        grid.add(new Separator(), 0, row++, 2, 1);
        
        
        // +++++++++++++ NumberOfApps ++++++++++++++ //
        grid.add(lbl_numberOfApps, 0, row);
        
        txf_numberOfApps.setMinWidth(50);
        txf_numberOfApps.setPrefWidth(50);
        txf_numberOfApps.setMaxWidth(50);
        txf_numberOfApps.setAlignment(Pos.CENTER_RIGHT);
        HBox hb_numberOfApps = new HBox(10);
		hb_numberOfApps.setAlignment(Pos.CENTER_RIGHT);
		hb_numberOfApps.getChildren().add(txf_numberOfApps);
        grid.add(hb_numberOfApps, 1, row++);
        
        // +++++++++++++ GENERATOR_OUTPUT_PATH ++++++++++++++ //
        // LBL GEN_OUTPUT_PATH
        grid.add(lbl_genOutputPath, 0, row);
        
        // BTN GEN_OUTPUT_PATH
        HBox hb_genOutputPath = new HBox(10);
		hb_genOutputPath.setAlignment(Pos.CENTER_RIGHT);
		hb_genOutputPath.getChildren().add(btn_genOutputPath);
		grid.add(hb_genOutputPath, 1, row++, 1, 2);
		
		// +++++++++++++ GEN_OUTPUT_PATH ++++++++++++++ //
		// TXF GEN_OUTPUT_PATH
		tx_genOutputPath.setWrappingWidth(350);
		tx_genOutputPath.setId("tx_genOutputPath");
        grid.add(tx_genOutputPath, 0, row++);
        
        // ---------------- SEPARATOR ---------------- //
        grid.add(new Separator(), 0, row++, 2, 1);
        
        // BTN GENERATE
        HBox hb_generator = new HBox(10);
        hb_generator.setAlignment(Pos.CENTER_RIGHT);
        hb_generator.getChildren().addAll(btn_generator);
		grid.add(hb_generator, 1, row++, 2, 1);
        
        
        
        
        /** +++++++++++++ SETTINGS Title (0) ++++++++++++++ **/
        tx_settings.setId("tx_settings");
        grid.add(tx_settings, 0, row++, 2, 1);

        // ---------------- SEPARATOR (1) ---------------- //
        grid.add(new Separator(), 0, row++, 2, 1);
        
        // +++++++++++++ INPUT_FILE_APPS (2) ++++++++++++++ //
        // LBL INPUT_FILE_APPS
        grid.add(lbl_inputFileApps, 0, row);
        
        // BTN INPUT_FILE_APPS
        HBox hb_inputFileApps = new HBox(10);
		hb_inputFileApps.setAlignment(Pos.CENTER_RIGHT);
		hb_inputFileApps.getChildren().add(btn_inputFileApps);
		grid.add(hb_inputFileApps, 1, row++, 1, 2);
		
		// +++++++++++++ INPUT_FILE_APPS (3) ++++++++++++++ //
		// TXF INPUT_FILE_APPS
		tx_inputFileApps.setWrappingWidth(350);
		tx_inputFileApps.setId("tx_inputFileApps");
        grid.add(tx_inputFileApps, 0, row++);
        
		// ---------------- SEPARATOR (4) ---------------- //
		grid.add(new Separator(), 0, row++, 2, 1);
        
        
        // +++++++++++++ CSV_Separator (x) ++++++++++++++ //
        grid.add(lbl_csvSeparator, 0, row);
        
        cbx_csvSeparator.getItems().addAll(";", ",");
        cbx_csvSeparator.setValue(Settings.getSeparator());
        HBox hb_csvSeparator = new HBox(10);
		hb_csvSeparator.setAlignment(Pos.CENTER_RIGHT);
		hb_csvSeparator.getChildren().add(cbx_csvSeparator);
        grid.add(hb_csvSeparator, 1, row++);
        
        // +++++++++++++ PMs (x) ++++++++++++++ //
        grid.add(lbl_PMs, 0, row);
        
        txf_PMs.setMinWidth(50);
        txf_PMs.setPrefWidth(50);
        txf_PMs.setMaxWidth(50);
        txf_PMs.setAlignment(Pos.CENTER_RIGHT);
        HBox hb_PMs = new HBox(10);
		hb_PMs.setAlignment(Pos.CENTER_RIGHT);
		hb_PMs.getChildren().add(txf_PMs);
        grid.add(hb_PMs, 1, row++);
        
        
        // +++++++++++++ CloudPartner (x) ++++++++++++++ //
        grid.add(lbl_cloudPartner, 0, row);
        
		txf_cloudPartner.setMinWidth(50);
		txf_cloudPartner.setPrefWidth(50);
		txf_cloudPartner.setMaxWidth(50);
        txf_cloudPartner.setAlignment(Pos.CENTER_RIGHT);
        HBox hb_cloudPartner = new HBox(10);
		hb_cloudPartner.setAlignment(Pos.CENTER_RIGHT);
		hb_cloudPartner.getChildren().add(txf_cloudPartner);
        grid.add(hb_cloudPartner, 1, row++);
        
        
        // +++++++++++++ Scenario (x) ++++++++++++++ //
        grid.add(lbl_scenario, 0, row);
        
        cbx_scenario.getItems().addAll(ScenarioEnum.A, ScenarioEnum.B, ScenarioEnum.C);
        cbx_scenario.setValue(Settings.getScenario());
        HBox hb_scenario = new HBox(10);
		hb_scenario.setAlignment(Pos.CENTER_RIGHT);
		hb_scenario.getChildren().add(cbx_scenario);
        grid.add(hb_scenario, 1, row++);
        
        
        // +++++++++++++ Scheduler (x) ++++++++++++++ //
        grid.add(lbl_scheduler, 0, row);
        
        cbx_scheduler.getItems().addAll(ScheduleStrategyEnum.A, ScheduleStrategyEnum.B, ScheduleStrategyEnum.C, ScheduleStrategyEnum.D);
        cbx_scheduler.setValue(Settings.getScheduler());
        HBox hb_scheduler = new HBox(10);
		hb_scheduler.setAlignment(Pos.CENTER_RIGHT);
		hb_scheduler.getChildren().add(cbx_scheduler);
        grid.add(hb_scheduler, 1, row++);
        
        
        
        // ---------------- SEPARATOR (4) ---------------- //
        grid.add(new Separator(), 0, row++, 2, 1);
        
        // +++++++++++++ OUTPUT_PATH (x) ++++++++++++++ //
        // LBL OUTPUT_PATH
        grid.add(lbl_outputPath, 0, row);
        
        // BTN OUTPUT_PATH
        HBox hb_outputPath = new HBox(10);
		hb_outputPath.setAlignment(Pos.CENTER_RIGHT);
		hb_outputPath.getChildren().add(btn_outputPath);
		grid.add(hb_outputPath, 1, row++, 1, 2);
		
		// +++++++++++++ OUTPUT_PATH (x) ++++++++++++++ //
		// TXF OUTPUT_PATH
		tx_outputPath.setWrappingWidth(350);
		tx_outputPath.setId("tx_outputPath");
        grid.add(tx_outputPath, 0, row++);
        
        // ---------------- SEPARATOR (x) ---------------- //
        grid.add(new Separator(), 0, row++, 2, 1);
        
        // BTN START
        HBox hb_start = new HBox(10);
		hb_start.setAlignment(Pos.CENTER_RIGHT);
		hb_start.getChildren().addAll(btn_reset, btn_start);
		grid.add(hb_start, 1, row++, 2, 1);
		
		
		
		
		// ######################## EVENTS #############################
		btn_genOutputPath.setOnAction(new EventHandler<ActionEvent>() {
        	public void handle(ActionEvent e) {
        		File file = new DirectoryChooser().showDialog(primaryStage);
        		if(file!=null) {
        			Settings.setGeneratorDirectory(file.getAbsolutePath());
        			tx_genOutputPath.setText(file.getAbsolutePath());
        		}
        	}
        });
		
		btn_generator.setOnAction(new EventHandler<ActionEvent>() {
			public void handle(ActionEvent e) {
				Settings.setGeneratorNumberOfApps(Integer.parseInt(txf_numberOfApps.getText()));
				InputDataGenerator idg = new InputDataGenerator();
				try {
					idg.createInputDataFile(ScenarioEnum.A);
					idg.createInputDataFile(ScenarioEnum.B);
					idg.createInputDataFile(ScenarioEnum.C);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		
		
		
		btn_inputFileApps.setOnAction(new EventHandler<ActionEvent>() {
			public void handle(ActionEvent e) {
				FileChooser fileChooser = new FileChooser();
				fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("CSV files (*.csv)", "*.csv"));
				File file = fileChooser.showOpenDialog(primaryStage);
				if(file != null){
					Settings.setInputFilePath(file.getAbsolutePath());
					tx_inputFileApps.setText(file.getAbsolutePath());
				}
			}
		});
		
		
		btn_outputPath.setOnAction(new EventHandler<ActionEvent>() {
        	public void handle(ActionEvent e) {
        		File file = new DirectoryChooser().showDialog(primaryStage);
        		if(file!=null) {
        			Settings.setSchedulerOutputDirectory(file.getAbsolutePath());
        			tx_outputPath.setText(file.getAbsolutePath());
        		}
        	}
        });
		
		btn_reset.setOnAction(new EventHandler<ActionEvent>() {
        	public void handle(ActionEvent e) {
        		Settings.resetToDefault();
        		txf_numberOfApps.setText(Settings.getGeneratorNumberOfApps().toString());
        		tx_genOutputPath.setText(Settings.getGeneratorDirectory());
        		tx_inputFileApps.setText(Settings.getInputFilePath());
        		cbx_csvSeparator.setValue(Settings.getSeparator());
        		txf_PMs.setText(Settings.getPmCount().toString());
        		txf_cloudPartner.setText(Settings.getCloudPartnerCount().toString());
        		cbx_scenario.setValue(Settings.getScenario());
        		cbx_scheduler.setValue(Settings.getScheduler());
        		tx_outputPath.setText(Settings.getSchedulerOutputDirectory());
        		SchedulerOutputFile.getInstance().clear();
        	}
        });
		
		btn_start.setOnAction(new EventHandler<ActionEvent>() {
        	public void handle(ActionEvent e) {
        		Settings.setSeparator(cbx_csvSeparator.getValue());
        		Settings.setPmCount(Integer.parseInt(txf_PMs.getText()));
        		Settings.setCloudPartnerCount(Integer.parseInt(txf_cloudPartner.getText()));
        		Settings.setScenario(cbx_scenario.getValue());
        		Settings.setScheduler(cbx_scheduler.getValue());
        		
        		Scheduler sch = new SchedulerImpl();
        		SchedulerOutputFile.getInstance().clear();
        		try {
					sch.schedule();
				} catch (SchedulerException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
        	}
        });
		

		
		
        
//        grid.setGridLinesVisible(true);
        
        Scene scene = new Scene(grid, 500, 600);
        primaryStage.setScene(scene);
        
        scene.getStylesheets().add(GUI.class.getResource("style.css").toExternalForm());
        primaryStage.show();
    }

	private TextField getNewNumTextField(String initValue) {
		return new TextField(initValue) {
		    @Override public void replaceText(int start, int end, String text) {
		        if (text.matches("[0-9]") || text.length() == 0)
		            super.replaceText(start, end, text);
		    }
		    @Override public void replaceSelection(String text) {
		        if (text.matches("[0-9]") || text.length() == 0)
		            super.replaceSelection(text);
		    }
		};
	}
}